﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.NonlinearEquationSolvers
{
    /// <summary>
    /// This class represents an abstract layer for all real nonlinear system of equation 
    /// solver classes.
    /// </summary>
    [Serializable]
    public abstract class AbstractRealNonLinearSystemSolver
    {
        /// <summary>
        /// The needed iterations for the calculation.
        /// </summary>
        protected int neededIterations;

        /// <summary>
        /// Saves if the calculation has a precision error.
        /// </summary>
        protected bool precisionError;

        /// <summary>
        /// The system of equation to solve.
        /// </summary>
        private NonLinearEquationSystem equationSystem;

        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractRealNonLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="equationSystem">The nonlinear system of equation to solve.</param>
        protected AbstractRealNonLinearSystemSolver(NonLinearEquationSystem equationSystem)
        {
            this.equationSystem = equationSystem;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractRealNonLinearSystemSolver"/> class.
        /// </summary>
        /// <param name="equationSystemFunctions">The nonlinear system of equation to solve.</param>
        protected AbstractRealNonLinearSystemSolver(HardMultivariateRealFunction[] equationSystemFunctions)
        {
            if (equationSystemFunctions == (HardMultivariateRealFunction[]) null)
            {
                throw new ArgumentNullException("equationSystemFunctions");
            }

            this.equationSystem = new NonLinearEquationSystem(equationSystemFunctions);
        }

        /// <summary>
        /// Gets a value indicating whether the calculation has a precision error.
        /// If true the result of the calculation has a precision error otherwise, false.
        /// </summary>
        /// <value>True the result of the calculation has a precision error otherwise, false.</value>
        public bool PrecisionError
        {
            get { return precisionError; }
        }

        /// <summary>
        /// Gets the needed iterations for the calculation.
        /// </summary>
        /// <value>The needed iterations for the calculation.</value>
        public int NeededIterations
        {
            get { return neededIterations; }
        }

        /// <summary>
        /// Gets or sets the nonlinear system of equation to solve.
        /// </summary>
        /// <value>The nonlinear system of equation to solve.</value>
        public NonLinearEquationSystem EquationSystem
        {
            get { return equationSystem; }
            set { equationSystem = value; }
        }

        /// <summary>
        /// Solves the nonlinear system of equation. The property PrecisionError have to be 
        /// checked after the calculation to be sure that the results are correct.
        /// </summary>
        /// <param name="startValues">The start values for the calculation.</param>
        /// <param name="iterations">The maximum number of iterations.</param>
        /// <param name="precision">The precision of the result.</param>
        /// <returns>The approximated numeric results, which solves the nonlinear system of equation.</returns>
        public abstract GeneralVector SolveNonLinearSystem(GeneralVector startValues, int iterations, double precision);
    }
}